package com.shiro.receiver.util;

import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
import org.bouncycastle.crypto.signers.Ed25519Signer;

import java.nio.charset.StandardCharsets;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class Ed25519Util {

    public static boolean verify(String secret, String message, String signature) {
        String seed = getSeed(secret);
        Ed25519PrivateKeyParameters privateKey = getPrivateKey(seed);
        Ed25519PublicKeyParameters publicKey = getPublicKey(privateKey);
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        Ed25519Signer verifier = new Ed25519Signer();
        verifier.init(false, publicKey);
        verifier.update(messageBytes, 0, messageBytes.length);
        return verifier.verifySignature(HexUtil.decodeHex(signature));
    }

    public static byte[] signToByteArray(String secret, String message) {
        String seed = getSeed(secret);
        Ed25519PrivateKeyParameters privateKey = getPrivateKey(seed);
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        Ed25519Signer signer = new Ed25519Signer();
        signer.init(true, privateKey);
        signer.update(messageBytes, 0, messageBytes.length);
        return signer.generateSignature();
    }

    public static String signToHexString(String secret, String message) {
        byte[] signByteArray = signToByteArray(secret, message);
        return HexUtil.encodeHexStr(signByteArray);
    }

    private static Ed25519PrivateKeyParameters getPrivateKey(String seed) {
        return new Ed25519PrivateKeyParameters(seed.getBytes(StandardCharsets.UTF_8), 0);
    }

    private static Ed25519PublicKeyParameters getPublicKey(Ed25519PrivateKeyParameters privateKey) {
        return privateKey.generatePublicKey();
    }

    private static String getSeed(String secret) {
        return StrUtil.repeatByLength(secret, 32);
    }

}
